#if !defined(__WIFI_H__)
#define __WIFI_H__

#include <string.h>
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_wifi.h"
#include "esp_mac.h"
#include "esp_event.h"
#include "lwip/err.h"
#include "lwip/sys.h"

#define WIFI_STATUS_INIT 0
#define WIFI_STATUS_DEINIT 1
#define WIFI_STATUS_START 2
#define WIFI_STATUS_STOP 3
#define WIFI_STATUS_STA_START 4
#define WIFI_STATUS_STA_STOP 5
#define WIFI_STATUS_STA_CONNECTING 6
#define WIFI_STATUS_STA_CONNECTED 7
#define WIFI_STATUS_STA_DISCONNECTED 8
#define WIFI_STATUS_AP_CONNECTED 9
#define WIFI_STATUS_AP_DISCONNECTED 10
#define WIFI_STATUS_SCAN_DONE 11
#define WIFI_STATUS_GOT_IP 12
#define WIFI_STATUS_LOST_IP 13
#define WIFI_STATUS_AP_GOT_IP 14
#define WIFI_STATUS_STA_CONNECT_RESULT 15
#define WIFI_STATUS_STA_SSID 16
#define WIFI_STATUS_MAX 17

extern const char *const WifiStatusType2Str[];

/* 智能热点(AP) + 常开终端(STA) 当 STA 连接后, 自动关闭AP, 当 STA 断开后, 自动开启AP */
#define WIFI_MODE_AUTO 0
/* 仅开启热点(长期开启AP) */
#define WIFI_MODE_ONLY_AP 1
/* 常开热点(AP) + 常开终端(STA) 不推荐 */
#define WIFI_MODE_AP_STA 2
/* 手动控制 */
#define WIFI_MODE_USER_CONFIG 3

#define WIFI_STORAGE_ENABLE_SIMPLE

#define DEFAULT_WIFI_AP_SSID "BAT-PB"
#define DEFAULT_WIFI_AP_PASSWD "12345678"

#ifdef __cplusplus
extern "C"
{
#endif

#pragma pack(1)
    typedef void (*wifi_status_notice_cb_t)(uint8_t status, void *value);
    typedef struct wifi_storage_info
    {
        char ssid[33];
        char passwd[33];
    } wifi_storage_info_s, *wifi_storage_info_t;

    typedef struct ip_config
    {
        uint32_t ip;
        uint32_t mask;
        uint32_t gateway;
    } wifi_ip_config;

    typedef struct wifi_storage
    {
#ifndef WIFI_STORAGE_ENABLE_SIMPLE
        int8_t cur_connect;
        uint8_t length : 4;
        uint8_t last_connect_state : 1;
#endif
        uint8_t init : 1;
        uint8_t mode : 2;
        uint8_t sta_ip_mode : 1;
        uint8_t dns_mode : 1;
        uint8_t ap_ip_mode : 1;
        wifi_ip_config sta_ip_config;
        wifi_ip_config ap_ip_config;
#ifndef WIFI_STORAGE_ENABLE_SIMPLE
        wifi_storage_info_s infos[12];
#else
    wifi_storage_info_s infos[1];
#endif
    } wifi_storage_s;

    typedef struct _wifi_stack
    {
        uint32_t MASGIC_START;
        esp_netif_t *sta_netif;
        esp_netif_t *ap_netif;
        esp_event_handler_instance_t instance_any_id;
        esp_event_handler_instance_t instance_got_ip;
        wifi_status_notice_cb_t notice_cb;
        uint32_t STORAGE_MASGIC_START;
        wifi_storage_s storage;
        uint32_t STORAGE_MASGIC_END;
        esp_netif_ip_info_t ip_info;
        wifi_ap_record_t scan_ap_infos[CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES];
        char *aps_ssid[CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES];
        int8_t aps_rssi[CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES];
        wifi_config_t config;
        uint8_t have_storage : 1;         /* 已拥有配置 */
        uint8_t s_retry_num : 3;          /* 连接wifi时, 失败重连次数 */
        uint8_t in_del : 1;               /* 处于wifi_del函数中 */
        uint8_t in_disconnect : 1;        /* 处于wifi_disconnect函数中 */
        uint8_t in_event_cb : 1;          /* 处于wifi事件回调中 */
        uint8_t user_call_scan : 1;       /* 用户调用扫描 */
        uint8_t user_call_disconnect : 1; /* 用户调用断开连接 */
        uint8_t user_call_connect : 1;    /* 用户调用连接 */
        uint8_t save_connect_state : 1;   /* 保存连接状态到NVS标志位 */
        uint8_t scan : 1;                 /* 扫描中状态 */
        uint8_t connect : 1;              /* 连接状态 */
        uint8_t connecting : 1;           /* 连接中状态 */
        uint8_t init : 1;                 /* 初始化状态 */
        uint8_t start : 1;                /* 启动状态 */
        uint8_t got_ip : 1;               /* 获取到IP状态 */
        uint8_t task_up : 1;              /* 任务启动标志 */
        uint16_t scan_ap_count;
        wifi_mode_t mode;
        char default_ap_ssid[33];
        char sta_ssid[33];
        char ip[16];
        char netmask[16];
        char gw[16];
        uint8_t buffer[4096]; /* 临时缓冲区 */
        uint32_t MASGIC_END;
    } wifi_stack_s, *wifi_stack_t;
#pragma pack()

    extern wifi_stack_t wifi_stack;
    void wifi_status_notice_cb(uint8_t status, void *value);
    void wifi_network_status_cb(bool status);

    void wifi_start_smartconfig(uint8_t type); /* type: smartconfig_type_t */
    void wifi_set_ap_dns(char *dns_str);
    void wifi_set_ap(char *ssid, char *passwd);
    void wifi_set_sta(char *ssid, char *passwd);
    void wifi_start_sta(void);
    void wifi_start_ap(void);
    void wifi_stop_ap(void);
    void wifi_init(void);
    void wifi_del(void);
    void wifi_bind_notice_cb(wifi_status_notice_cb_t cb);
    /* scan */
    uint8_t wifi_scan_start(uint8_t block);
    uint16_t wifi_get_scan_ap_num(void);
    wifi_ap_record_t *wifi_get_scan_ap_info(void);
    int8_t wifi_get_scan_ap_info_to(char *to, uint16_t size);
    char *wifi_get_sta_ssid(void);
    char *wifi_get_ap_ssid(void);
    char *wifi_get_ap_passwd(void);
    char *wifi_storage_get(char *ssid);
    wifi_storage_info_t wifi_storage_get_last_connect();

    void wifi_start(void);
    void wifi_stop(void);
    void wifi_disconnect(void);

    uint32_t wifi_get_localIP();
    uint32_t wifi_get_subnetMask();
    uint32_t wifi_get_gateway();

    uint8_t wifi_storage_commit(void);
    uint8_t wifi_storage_delete(char *ssid);
    uint8_t wifi_storage_get_kes(char *buff);
    uint8_t wifi_storage_check(char *ssid);
    bool wifi_overflow_check();

#ifdef __cplusplus
}
#endif
#endif // __WIFI_H__
